import React, { useMemo, useState, useEffect, useRef, useCallback } from 'react';
import { Table, PageHeader, Button, Search, Tabs, Icon, ImportExport, units, Formx, ActionText } from '@library';
import { ListPageProps, ButtonProps, BtnClickEvent, ImportExportProps } from './interface';
import { ColumnProps } from '@library/components/table/interface';
import { useHistory } from 'react-router-use-history';
import { parse } from '@library/utils/json/json';
import { Row, Col, message } from 'antd';
import ApiQueryProps from './../../interface/apiQuery';
import { TableRefProps } from './../table/interface';
import i18n from './../../app/i18n';
import { FormxRefProps } from '@library/components/formx/interface';

const gutter = [10, 0];

export default ({ table, actions, searchColumns: propSearchColumns, tabs, importExport: propImportExport, noBreadcrumb, advancedSearchFormItems, detailsUrl }: ListPageProps) => {

  const history = useHistory();
  const queryTimeout = useRef<any>(null);
  const tableRef = useRef<TableRefProps>(null);
  const formxRef = useRef<FormxRefProps>(null);
  const [query, setQuery] = useState<ApiQueryProps>({});
  const [curTabId, setCurTabId] = useState('');
  const [url, setUrl] = useState('');
  const [columns, setColumns] = useState<ColumnProps<any>[]>([]);

  useEffect(() => {
    if (tabs?.length) setCurTabId(tabs[0].id);
  }, [tabs]);

  useEffect(() => {
    if (curTabId) {
      const query = tabs?.find(item => item.id === curTabId)?.query;
      updateQuery(typeof query === 'string' ? parse(query) : query);
      return setUrl(tabs?.find(item => item.id === curTabId)?.url || '');
    }
    setUrl(table.url || '');
  }, [curTabId, tabs, table.url]);

  useEffect(() => {
    if (!curTabId) return setColumns(table.columns);

    const columns = tabs?.find(item => item.id === curTabId)?.columns;
    if (!columns || !columns.length) return setColumns(table.columns);

    const tableColumns = table.columns.reduce((next, cur) => (next[cur.dataIndex as string] = cur) && next, {});
    setColumns(columns?.map(item => tableColumns[item]).filter(item => item))
  }, [curTabId, table.columns, tabs]);

  function btnOnClick(e: BtnClickEvent, item: ButtonProps) {
    if (item.pathname) return history.push(item.pathname);
    item.onClick?.(e);
  }

  function updateQuery(query: ApiQueryProps) {
    if (queryTimeout.current) {
      clearTimeout(queryTimeout.current);
      queryTimeout.current = null;
    }
    queryTimeout.current = setTimeout(() => {
      setQuery(query);
      queryTimeout.current = null;
    }, 200)
  }

  const searchColumns = useMemo(() => {
    return columns.filter(item => item.filter).map(item => item.dataIndex)
  }, [propSearchColumns, columns]);

  const importExport = useMemo(() => {
    if (propImportExport) return propImportExport;
    const importExport = actions?.find(item => (item.type as any) === 'importExport')
    return importExport as ImportExportProps
  }, [propImportExport, actions]);

  const Title = useMemo(() => {
    if (tabs?.length) {

      const language = i18n.language === 'zh-CN' ? 'cn' : i18n.language;
      const handleTabs = tabs?.map(item => ({ ...item, label: item.label || item.locales?.[language] }));

      return <Tabs mode='tabs' onChange={setCurTabId} curTabId={curTabId} tabs={handleTabs} />
    }
  }, [tabs, curTabId, noBreadcrumb]);

  const onSearch = useCallback((fuzzyValue: string) => {
    updateQuery({ ...query, fuzzyQuery: true, fuzzyValue, fuzzyField: searchColumns as string[] })
  }, [query, searchColumns]);

  const advancedSearch = useCallback(async () => {
    const data = await formxRef.current?.validateFields();
    if (data) updateQuery({ ...query, where: { ...query.where, ...data } });
  }, [query]);

  const advancedReset = useCallback(() => {
    formxRef.current?.resetFields()
  }, []);

  const importServer = useCallback((data: any[]) => {
    if (importExport?.importServerUrl) {
      units.server(importExport?.importServerUrl, { data }).then(() => {
        tableRef.current?.onRefresh();
        message.success(window.$app.t('importSucceeded'));
      }).catch(() => {
        message.error(window.$app.t('importError'));
      })
    }
  }, [importExport]);

  const placeholder = useMemo(() => {
    const tips = searchColumns?.map(item => window.$app.t(item as string)).join('/');
    return window.$app.t('pleaseEnter') + tips
  }, [searchColumns]);

  function toDetailsPage(record: any){
    window.sessionStorage.setItem('listPageItem', JSON.stringify(record));
    if(detailsUrl) return history.push(`${detailsUrl}?id=${record.id}`);
    const pathname = history.location.pathname;
    history.push(`${pathname}/details?id=` + record.id);
  }

  const TableActions = useMemo(() => [
    {
      dataIndex: 'action', render: (text: string, record: any) => (
        <ActionText onClick={() => toDetailsPage(record)}>详情</ActionText>
      )
    }
  ], [history, detailsUrl]);

  const onDoubleClick = useCallback(toDetailsPage, []);

  return (
    <div className='common-block-table'>
      <PageHeader title={Title} extra={
        <Row gutter={gutter as any}>
          {(searchColumns && searchColumns.length) ? (
            <Col>
              <Search advancedReset={advancedReset} advancedSearch={advancedSearch} placeholder={placeholder} onSearch={onSearch}
                suffix={advancedSearchFormItems && <Formx ref={formxRef} formItems={advancedSearchFormItems} />} />
            </Col>
          ) : null}

          {actions?.map(item => {
            const Btn = item.btnType ? Button[item.btnType] : null;
            return Btn ? <Col><Btn onClick={(e: BtnClickEvent) => btnOnClick(e, item)} /></Col> : null
          })}

          {importExport && <ImportExport importServer={importServer} {...importExport} />}
        </Row>
      } />
      <div className='common-white-space'/>
      <Table ref={tableRef} query={query} {...table} columns={columns} url={url} extra={TableActions} onDoubleClick={onDoubleClick}/>
    </div>
  )
}